#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================
print "importo dbfacade"

#from debug import DEBUG
#import gap.gException as gException
#from gap.gLocalize import _
#from gap.gException import gException,gError
#from gap import DB_TYPE,SCHEMA_NAME,MODULES
#from gap.gConstants import *

from koro.db import session

class DbFacade(object):
    __instance = None
    __err = "E' consentita l'esisteza di una sola istanza"
    @staticmethod
    def get_instance():
        return (DbFacade.__instance or DbFacade())
    
    def __init__(self):
        err = DbFacade.__err
        assert DbFacade.__instance is None, Exception(err)
        DbFacade.__instance = self
        self.__session = None
    
    def configure(self,configuration):    
        self.__session=session.Session()
        self.__session.configure(configuration)
    
    def close(self):
        self.__session.close()
        
    def validate_and_save(self,obj):
        '''Aggiunge un oggetto alla sessione e chiama commit. '''
        print self.__class__.__name__,'save'
        obj.validate()
        self.save(obj)
        obj.pending = False
        obj.cascading = False
        #s.close()
    
    def validate_and_add(self,obj):
        '''Aggiunge un oggetto alla sessione e chiama commit. '''
        print self.__class__.__name__,'save'
        obj.validate()
        self.add(obj)
    
    def save(self,obj):
        '''Aggiunge un oggetto alla sessione e chiama commit. '''
        print self.__class__.__name__,'save'
        s=self.__session.get_current_session()
        s.add(obj)
        #s.flush()
        s.commit()
        #s.close()
    
    def add(self,obj):
        '''Aggiunge un oggetto alla sessione senza chiamare commit. '''
        print self.__class__.__name__,'add'
        s=self.__session.get_current_session()
        s.add(obj)
        s.flush()
    
    def delete(self,obj):
        s=self.__session.get_current_session()
        s.delete(obj)
        s.commit()
    
    def remove(self,obj):
        '''A differenza di delete non esegue commit.'''
        s=self.__session.get_current_session()
        s.delete(obj)
    
    def load(self,class_):
        s=self.__session.get_current_session()
        _list=s.query(class_).all()        
        
        return _list
    
    def query(self,class_):
        s=self.__session.get_current_session()
        q=s.query(class_)
        return q
    
    def commit(self):
        self.__session.get_current_session().commit()
    
    def flush(self):
        self.__session.get_current_session().flush()
    
    def rollback(self):
        self.__session.get_current_session().rollback()
    
    def expunge(self,obj):
        s=self.__session.get_current_session()
        s.expunge(obj)
        s.flush()
    
    def expire(self,obj):
        self.__session.get_current_session().expire(obj)
    
    def refresh(self,obj):
        self.__session.get_current_session().refresh(obj)
    
    def clear(self):        
        self.__session.get_current_session().expunge_all()
        
    def get_connection_info(self):
        return self.__session.get_connection_info()
    
    def save_connection_info(self,info):
        self.__session.save_connection_info(info)
    
#    def bind(self,obj):
#        s=self.__session.get_session()
#        s.add(obj)

        
        
#    def load__old(self,*args,**kwargs):
#        class_name=args[0].__name__
#        sql=query.select_query[class_name]
#        sql+=" where %s" % kwargs['where']
#        return self.__backend.execute_sql(sql)
#    
#    def load_all__old(self,class_name):
#        sql=query.select_query[class_name]
#        return self.__backend.execute_sql(sql)
    
    
#    #metodi per la nuova gestione modulare
#    def onGet(self,srcCode,logic=None):
#        mod=self.__mod[srcCode]
#        selectInfo=mod.gGetSelectInfo(mod,srcCode,logic)
#        return self.__db.doSelect(selectInfo)        
#    
#    def onSave(self,srcCode,data):
#        mod=self.__mod[srcCode]
#        print data,'dbfacade.onsave'
#        print srcCode,self.__mod
#        insertInfo=mod.gGetInsertInfo(mod,srcCode,data)
#        if self.__db.doInsert(insertInfo):
#            selectInfo=mod.gGetSelectInfo(mod,srcCode,None)
#            return self.__db.doSelect(selectInfo)
#        #che succede qui?
#        #raise gException.gDBOperationException(_("Si e' verificato un errore!"))
#
#    def onDelete(self,srcCode,logic):
#        print 'dbfacade.onDelete'
#        mod=self.__mod[srcCode]
#        deleteInfo=mod.gGetDeleteInfo(mod,srcCode,logic)
#        selectInfo=mod.gGetSelectInfo(mod,srcCode,logic)
#        trash=self.__db.doSelect(selectInfo)
#        print 'dopo trash'
#        if self.__db.doDelete(deleteInfo,trash[0]):
#            selectInfo=mod.gGetSelectInfo(mod,srcCode,None)
#            return self.__db.doSelect(selectInfo)
#        #che succede qui?
#        raise gException.gDBOperationException(_("Si e' verificato un errore!"))
#
#    def onNewTab(self,table,table_old):
#        print 'dbfacade.onNewTab'
#
#        sql="""CREATE TABLE %s (
#  `codice` varchar(10) NOT NULL,
#  `descrizione` varchar(150) default NULL,
#  `umprod` varchar(150) default NULL,
#  `prezzo` varchar(6) default NULL,
#  `fk_listino` int(10) unsigned NOT NULL,
#  PRIMARY KEY  (`codice`),
#  CONSTRAINT FOREIGN KEY (`fk_listino`) REFERENCES `listini` (`ID_listino`)
#) ENGINE=InnoDB DEFAULT CHARSET=latin1""" % table
#        
#        self.__db.execSql(sql)
#        #self.__db.createTable(table,table_old)
#
#    def onDelTab(self,table):
#        print 'dbfacade.onDelTab'
#        self.__db.deleteTable(table)


class ConnectionInfo(object):
    """ Holder for the properties for connecting to the backend. Each 
    backend may have different names for properties, but this object
    tries to abstract that. The value stored in the Password must be 
    encrypted in the format set in the app. This class has  'encrypt' and
    'decrypt' functions for doing this, or you can set the PlainTextPassword
    property, and the class will encypt that value and set the Password
    property for you.
    
    You can create it in several ways, like most Dabo objects. First, you 
    can pass all the settings as parameters to the constructor:
    
        ci = gConnectInfo(DbType="MySQL", Host="domain.com",
            User="daboUser", PlainTextPassword="secret", Port=3306,
            Database="myData", Name="mainConnection")
            
    Or you can create a dictionary of the various props, and pass that
    in the 'connInfo' parameter:
    
        connDict = {"DbType" : "MySQL", "Host" : "domain.com",
            "User" : "daboUser", "PlainTextPassword" : "secret", 
            "Port" : 3306, "Database" : "myData", "Name" : "mainConnection"}
        ci = gConnectInfo(connInfo=connDict)
        
    Or, finally, you can create the object and then set the props
    individually:

        ci = gConnectInfo()
        ci.DbType = "MySQL"
        ci.Host = "domain.com"
        ci.User = "daboUser"
        ci.PlainTextPassword = "secret"
        ci.Database = "myData"
        ci.Name = "mainConnection"
    """
    def __init__(self,*args,**kwargs):
        self._host = kwargs['host']
        self._user = kwargs['user']
        self._password = kwargs['passwd']
        self._backend = kwargs['backend']
        self._database = kwargs['database']
        self._port = kwargs['port']
        self._name = ""
        
    def _get_backend(self): 
        return self._backend
                
    def _set_backend(self, b_end):
        """ Set the backend type for the connection if valid. """
        self._backend = b_end.lower()

    def _get_database(self):
        return self._database

    def _set_database(self, database): 
        self._database = database

    def _get_host(self):
        return self._host

    def _set_host(self, host): 
        self._host = host

    def _get_name(self):
        return self._name

    def _set_name(self, val):
        self._name = val
        
    def _get_user(self):
        return self._user

    def _set_user(self, user):
        self._user = user

    def _get_password(self):
        return self._password

    def _set_password(self, password):
        self._password = password

    def _get_port(self):
        return self._port

    def _set_port(self, port):
        self._port = port
        
    backend = property(_get_backend, _set_backend, None,"Name of the backend database type.  (str)")

    database = property(_get_database, _set_database, None,"The database name to login to. (str)")

    host = property(_get_host, _set_host, None,"The host name or ip address. (str)")

    name = property(_get_name, _set_name, None,"The name used to reference this connection. (str)")

    password = property(_get_password, _set_password, None,"The encrypted password of the user. (str)")    
    
    port = property(_get_port, _set_port, None,"The port to connect on (may not be applicable for all databases). (int)")

    user = property(_get_user, _set_user, None,"The user name. (str)")
